﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;

namespace MadLibrary.Net.Server
{
    /// <summary>
    /// Holds basic methods, properties and functions of server.
    /// </summary>
    public abstract class Server
    {
        /// <summary>
        /// Represents port which has to be listened for connections.
        /// </summary>
        public int ListeningPort { get; set; }
        /// <summary>
        /// Holds key status of server.
        /// </summary>
        public bool Running { get; set; }
        /// <summary>
        /// Holds instance of socket which has to be used for listening.
        /// </summary>
        protected Socket sock { get; set; }
        /// <summary>
        /// Base of implicit constructor for child classes which sets properties to thier default values.
        /// </summary>
        public Server()
        {
            this.ListeningPort = 1025;
            this.sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }
        /// <summary>
        /// Represents base of overloaded constructor for child classes which sets properties to thier default values and listening port to value specified.
        /// </summary>
        /// <param name="ListeningPort">Specifies number of port which has to be listened for incoming coonnections.</param>
        public Server(int ListeningPort)
        {
            this.ListeningPort = ListeningPort;
            this.sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }
        /// <summary>
        /// Starts listening on port specified as value of ListeningPort property in new thread and sets status property to running (true).
        /// </summary>
        public void Start()
        {
            this.Running = true;
            new Thread(new ThreadStart(() => {
                sock.Bind(new IPEndPoint(IPAddress.Any, this.ListeningPort));
                sock.Listen(100);
                while (this.Running)
                {
                    Socket client = this.sock.Accept();
                    new Thread(new ThreadStart(() => { this.Process(client); })).Start();
                }
            })).Start();
        }
        /// <summary>
        /// Represents base of connected client pararell process method for child classes.
        /// </summary>
        /// <param name="client">Specifies client instance which will be accepted in listening thread loop.</param>
        public virtual void Process(Socket client)
        { 
            
        }
        /// <summary>
        /// Serves as ender of pararell listening loop.
        /// </summary>
        public void End()
        {
            this.Running = false;
        }
        /// <summary>
        /// Serves as base of finalization for child classes. Contains pararell listeing loop ender.
        /// </summary>
        ~Server()
        {
            this.End();
        }
    }
}
